﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using FlowBasis.Json;
using FlowBasis.Web.Configuration;

namespace FlowBasis.Web.Mvc
{
    public class PostRpcResult : ActionResult
    {
        private object result;
        private Exception exception;

        public PostRpcResult(object result)
        {
            this.result = result;
        }

        public PostRpcResult(Exception exception)
        {
            this.exception = exception;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
                throw new ArgumentNullException("context");

            dynamic response;

            if (this.exception != null)
            {
                var jsSettings = FlowBasis.Services.ServiceResolver.Instance.Get<IJavascriptSettingsService>();
                bool includeDetails = jsSettings.IncludeFullExceptionDetailsForPostRpc;

                response = new JObject();
                response.result = null;
                response.error = this.GetExceptionJObject(this.exception, includeDetails);
            }
            else
            {
                // TODO: See if we need to correlate a message id from the initial request.
                var jObjectRootMapper = FlowBasis.Services.ServiceResolver.Instance.Get<IJObjectRootMapper>();
                object jObjectResult = jObjectRootMapper.ToJObject(result);

                response = new JObject();
                response.result = jObjectResult;
            }
            
            var httpResponse = context.HttpContext.Response;       
            httpResponse.ContentType = "application/json";

            var jsonSerializer = FlowBasis.Services.ServiceResolver.Instance.Get<IJsonSerializationService>();
            var responseJson = jsonSerializer.Stringify(response);
            httpResponse.Write(responseJson);            
        }


        private JObject GetExceptionJObject(Exception exception, bool includeDetail)
        {            
            JObject ex = new JObject();
            ex["message"] = exception.Message;

            if (includeDetail)
            {
                ex["stackTrace"] = exception.StackTrace;

                if (exception.InnerException != null)
                {
                    ex["innerException"] = this.GetExceptionJObject(exception.InnerException, includeDetail);
                }
            }

            return ex;
        }
    }
}
